home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / aplictns / xscheme2 / part02 < prev    next >
Encoding:
Internet Message Format  |  1990-04-14  |  50.1 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i140: XScheme 0.20 - an object-oriented scheme, Part02/07
  5. Message-ID: <12210@xanth.cs.odu.edu>
  6. Date: 14 Apr 90 21:09:16 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: rusty@fe2o3.UUCP (Rusty Haddock)
  9. Lines: 2118
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: rusty@fe2o3.UUCP (Rusty Haddock)
  15. Posting-number: Volume 90, Issue 140
  16. Archive-name: applications/xscheme-0.20/part02
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 2 (of 7)."
  25. # Contents:  Src/msstuff.c Src/xsimage.c Src/xsint.c Src/xsobj.c
  26. #   Src/xsread.c
  27. # Wrapped by tadguy@xanth on Sat Apr 14 17:07:22 1990
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'Src/msstuff.c' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'Src/msstuff.c'\"
  31. else
  32. echo shar: Extracting \"'Src/msstuff.c'\" \(8253 characters\)
  33. sed "s/^X//" >'Src/msstuff.c' <<'END_OF_FILE'
  34. X/* msstuff.c - ms-dos specific routines */
  35. X
  36. X#include <dos.h>
  37. X#include "xscheme.h"
  38. X
  39. X#define LBSIZE 200
  40. X
  41. X/* external variables */
  42. Xextern LVAL s_unbound,true;
  43. Xextern FILE *tfp;
  44. Xextern int errno;
  45. X
  46. X/* local variables */
  47. Xstatic char lbuf[LBSIZE];
  48. Xstatic int lpos[LBSIZE];
  49. Xstatic int lindex;
  50. Xstatic int lcount;
  51. Xstatic int lposition;
  52. Xstatic long rseed = 1L;
  53. X
  54. X/* osinit - initialize */
  55. Xosinit(banner)
  56. X  char *banner;
  57. X{
  58. X    printf("%s\n",banner);
  59. X    lposition = 0;
  60. X    lindex = 0;
  61. X    lcount = 0;
  62. X}
  63. X
  64. X/* osfinish - clean up before returning to the operating system */
  65. Xosfinish()
  66. X{
  67. X}
  68. X
  69. X/* oserror - print an error message */
  70. Xoserror(msg)
  71. X  char *msg;
  72. X{
  73. X    printf("error: %s\n",msg);
  74. X}
  75. X
  76. X/* osrand - return a random number between 0 and n-1 */
  77. Xint osrand(n)
  78. X  int n;
  79. X{
  80. X    long k1;
  81. X
  82. X    /* make sure we don't get stuck at zero */
  83. X    if (rseed == 0L) rseed = 1L;
  84. X
  85. X    /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
  86. X    k1 = rseed / 127773L;
  87. X    if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
  88. X    rseed += 2147483647L;
  89. X
  90. X    /* return a random number between 0 and n-1 */
  91. X    return ((int)(rseed % (long)n));
  92. X}
  93. X
  94. X/* osaopen - open an ascii file */
  95. XFILE *osaopen(name,mode)
  96. X  char *name,*mode;
  97. X{
  98. X    return (fopen(name,mode));
  99. X}
  100. X
  101. X/* osbopen - open a binary file */
  102. XFILE *osbopen(name,mode)
  103. X  char *name,*mode;
  104. X{
  105. X    char bmode[10];
  106. X    strcpy(bmode,mode); strcat(bmode,"b");
  107. X    return (fopen(name,bmode));
  108. X}
  109. X
  110. X/* osclose - close a file */
  111. Xint osclose(fp)
  112. X  FILE *fp;
  113. X{
  114. X    return (fclose(fp));
  115. X}
  116. X
  117. X/* ostell - get the current file position */
  118. Xlong ostell(fp)
  119. X  FILE *fp;
  120. X{
  121. X    return (ftell(fp));
  122. X}
  123. X
  124. X/* osseek - set the current file position */
  125. Xint osseek(fp,offset,whence)
  126. X  FILE *fp; long offset; int whence;
  127. X{
  128. X    return (fseek(fp,offset,whence));
  129. X}
  130. X
  131. X/* osagetc - get a character from an ascii file */
  132. Xint osagetc(fp)
  133. X  FILE *fp;
  134. X{
  135. X    return (getc(fp));
  136. X}
  137. X
  138. X/* osaputc - put a character to an ascii file */
  139. Xint osaputc(ch,fp)
  140. X  int ch; FILE *fp;
  141. X{
  142. X    return (putc(ch,fp));
  143. X}
  144. X
  145. X/* osbgetc - get a character from a binary file */
  146. Xint osbgetc(fp)
  147. X  FILE *fp;
  148. X{
  149. X    return (getc(fp));
  150. X}
  151. X
  152. X/* osbputc - put a character to a binary file */
  153. Xint osbputc(ch,fp)
  154. X  int ch; FILE *fp;
  155. X{
  156. X    return (putc(ch,fp));
  157. X}
  158. X
  159. X/* ostgetc - get a character from the terminal */
  160. Xint ostgetc()
  161. X{
  162. X    int ch;
  163. X
  164. X    /* check for a buffered character */
  165. X    if (lcount--)
  166. X    return (lbuf[lindex++]);
  167. X
  168. X    /* get an input line */
  169. X    for (lcount = 0; ; )
  170. X    switch (ch = xgetc()) {
  171. X    case '\r':
  172. X        lbuf[lcount++] = '\n';
  173. X        xputc('\r'); xputc('\n'); lposition = 0;
  174. X        if (tfp)
  175. X            for (lindex = 0; lindex < lcount; ++lindex)
  176. X            osaputc(lbuf[lindex],tfp);
  177. X        lindex = 0; lcount--;
  178. X        return (lbuf[lindex++]);
  179. X    case '\010':
  180. X    case '\177':
  181. X        if (lcount) {
  182. X            lcount--;
  183. X            while (lposition > lpos[lcount]) {
  184. X            xputc('\010'); xputc(' '); xputc('\010');
  185. X            lposition--;
  186. X            }
  187. X        }
  188. X        break;
  189. X    case '\032':
  190. X        xflush();
  191. X        return (EOF);
  192. X    default:
  193. X        if (ch == '\t' || (ch >= 0x20 && ch < 0x7F)) {
  194. X            lbuf[lcount] = ch;
  195. X            lpos[lcount] = lposition;
  196. X            if (ch == '\t')
  197. X            do {
  198. X                xputc(' ');
  199. X            } while (++lposition & 7);
  200. X            else {
  201. X            xputc(ch); lposition++;
  202. X            }
  203. X            lcount++;
  204. X        }
  205. X        else {
  206. X            xflush();
  207. X            switch (ch) {
  208. X            case '\003':    xltoplevel();    /* control-c */
  209. X            case '\007':    xlcleanup();    /* control-g */
  210. X            case '\020':    xlcontinue();    /* control-p */
  211. X            case '\032':    return (EOF);    /* control-z */
  212. X            default:        return (ch);
  213. X            }
  214. X        }
  215. X    }
  216. X}
  217. X
  218. X/* ostputc - put a character to the terminal */
  219. Xostputc(ch)
  220. X  int ch;
  221. X{
  222. X    /* check for control characters */
  223. X    oscheck();
  224. X
  225. X    /* output the character */
  226. X    if (ch == '\n') {
  227. X    xputc('\r'); xputc('\n');
  228. X    lposition = 0;
  229. X    }
  230. X    else {
  231. X    xputc(ch);
  232. X    lposition++;
  233. X   }
  234. X
  235. X   /* output the character to the transcript file */
  236. X   if (tfp)
  237. X    osaputc(ch,tfp);
  238. X}
  239. X
  240. X/* osflush - flush the terminal input buffer */
  241. Xosflush()
  242. X{
  243. X    lindex = lcount = lposition = 0;
  244. X}
  245. X
  246. X/* oscheck - check for control characters during execution */
  247. Xoscheck()
  248. X{
  249. X    int ch;
  250. X    if (ch = xcheck())
  251. X    switch (ch) {
  252. X    case '\002':    /* control-b */
  253. X        xflush();
  254. X        xlbreak("BREAK",s_unbound);
  255. X        break;
  256. X    case '\003':    /* control-c */
  257. X        xflush();
  258. X        xltoplevel();
  259. X        break;
  260. X    case '\024':    /* control-t */
  261. X        xinfo();
  262. X        break;
  263. X    case '\023':    /* control-s */
  264. X        while (xcheck() != '\021')
  265. X        ;
  266. X        break;
  267. X    }
  268. X}
  269. X
  270. X/* xinfo - show information on control-t */
  271. Xstatic xinfo()
  272. X{
  273. X/*
  274. X    extern int nfree,gccalls;
  275. X    extern long total;
  276. X    char buf[80];
  277. X    sprintf(buf,"\n[ Free: %d, GC calls: %d, Total: %ld ]",
  278. X        nfree,gccalls,total);
  279. X    errputstr(buf);
  280. X*/
  281. X}
  282. X
  283. X/* xflush - flush the input line buffer and start a new line */
  284. Xstatic xflush()
  285. X{
  286. X    osflush();
  287. X    ostputc('\n');
  288. X}
  289. X
  290. X/* xgetc - get a character from the terminal without echo */
  291. Xstatic int xgetc()
  292. X{
  293. X    return (bdos(7,0,0) & 0xFF);
  294. X}
  295. X
  296. X/* xputc - put a character to the terminal */
  297. Xstatic xputc(ch)
  298. X  int ch;
  299. X{
  300. X    bdos(6,ch,0);
  301. X}
  302. X
  303. X/* xcheck - check for a character */
  304. Xstatic int xcheck()
  305. X{
  306. X    return (bdos(6,0xFF,0) & 0xFF);
  307. X}
  308. X
  309. X/* xinbyte - read a byte from an input port */
  310. XLVAL xinbyte()
  311. X{
  312. X    int portno;
  313. X    LVAL val;
  314. X    val = xlgafixnum(); portno = (int)getfixnum(val);
  315. X    xllastarg();
  316. X    return (cvfixnum((FIXTYPE)inp(portno)));
  317. X}
  318. X
  319. X/* xoutbyte - write a byte to an output port */
  320. XLVAL xoutbyte()
  321. X{
  322. X    int portno,byte;
  323. X    LVAL val;
  324. X    val = xlgafixnum(); portno = (int)getfixnum(val);
  325. X    val = xlgafixnum(); byte = (int)getfixnum(val);
  326. X    xllastarg();
  327. X    outp(portno,byte);
  328. X    return (NIL);
  329. X}
  330. X
  331. X/* xint86 - invoke a system interrupt */
  332. XLVAL xint86()
  333. X{
  334. X    union REGS inregs,outregs;
  335. X    struct SREGS sregs;
  336. X    LVAL inv,outv,val;
  337. X    int intno;
  338. X
  339. X    /* get the interrupt number and the list of register values */
  340. X    val = xlgafixnum(); intno = (int)getfixnum(val);
  341. X    inv = xlgavector();
  342. X    outv = xlgavector();
  343. X    xllastarg();
  344. X
  345. X    /* check the vector lengths */
  346. X    if (getsize(inv) != 9)
  347. X        xlerror("incorrect vector length",inv);
  348. X    if (getsize(outv) != 9)
  349. X    xlerror("incorrect vector length",outv);
  350. X
  351. X    /* load each register from the input vector */
  352. X    val = getelement(inv,0);
  353. X    inregs.x.ax = (fixp(val) ? (int)getfixnum(val) : 0);
  354. X    val = getelement(inv,1);
  355. X    inregs.x.bx = (fixp(val) ? (int)getfixnum(val) : 0);
  356. X    val = getelement(inv,2);
  357. X    inregs.x.cx = (fixp(val) ? (int)getfixnum(val) : 0);
  358. X    val = getelement(inv,3);
  359. X    inregs.x.dx = (fixp(val) ? (int)getfixnum(val) : 0);
  360. X    val = getelement(inv,4);
  361. X    inregs.x.si = (fixp(val) ? (int)getfixnum(val) : 0);
  362. X    val = getelement(inv,5);
  363. X    inregs.x.di = (fixp(val) ? (int)getfixnum(val) : 0);
  364. X    val = getelement(inv,6);
  365. X    sregs.es = (fixp(val) ? (int)getfixnum(val) : 0);
  366. X    val = getelement(inv,7);
  367. X    sregs.ds = (fixp(val) ? (int)getfixnum(val) : 0);
  368. X    val = getelement(inv,8);
  369. X    inregs.x.cflag = (fixp(val) ? (int)getfixnum(val) : 0);
  370. X
  371. X    /* do the system interrupt */
  372. X    int86x(intno,&inregs,&outregs,&sregs);
  373. X
  374. X    /* store the results in the output vector */
  375. X    setelement(outv,0,cvfixnum((FIXTYPE)outregs.x.ax));
  376. X    setelement(outv,1,cvfixnum((FIXTYPE)outregs.x.bx));
  377. X    setelement(outv,2,cvfixnum((FIXTYPE)outregs.x.cx));
  378. X    setelement(outv,3,cvfixnum((FIXTYPE)outregs.x.dx));
  379. X    setelement(outv,4,cvfixnum((FIXTYPE)outregs.x.si));
  380. X    setelement(outv,5,cvfixnum((FIXTYPE)outregs.x.di));
  381. X    setelement(outv,6,cvfixnum((FIXTYPE)sregs.es));
  382. X    setelement(outv,7,cvfixnum((FIXTYPE)sregs.ds));
  383. X    setelement(outv,8,cvfixnum((FIXTYPE)outregs.x.cflag));
  384. X    
  385. X    /* return the result list */
  386. X    return (outv);
  387. X}
  388. X
  389. X/* getnext - get the next fixnum from a list */
  390. Xstatic int getnext(plist)
  391. X  LVAL *plist;
  392. X{
  393. X    LVAL val;
  394. X    if (consp(*plist)) {
  395. X        val = car(*plist);
  396. X    *plist = cdr(*plist);
  397. X    if (!fixp(val))
  398. X        xlerror("expecting an integer",val);
  399. X        return ((int)getfixnum(val));
  400. X    }
  401. X    return (0);
  402. X}
  403. X
  404. X/* xsystem - execute a system command */
  405. XLVAL xsystem()
  406. X{
  407. X    char *cmd="COMMAND";
  408. X    if (moreargs())
  409. X    cmd = (char *)getstring(xlgastring());
  410. X    xllastarg();
  411. X    return (system(cmd) == 0 ? true : cvfixnum((FIXTYPE)errno));
  412. X}
  413. X
  414. X/* xgetkey - get a key from the keyboard */
  415. XLVAL xgetkey()
  416. X{
  417. X    xllastarg();
  418. X    return (cvfixnum((FIXTYPE)xgetc()));
  419. X}
  420. X
  421. X/* ossymbols - enter os specific symbols */
  422. Xossymbols()
  423. X{
  424. X}
  425. END_OF_FILE
  426. if test 8253 -ne `wc -c <'Src/msstuff.c'`; then
  427.     echo shar: \"'Src/msstuff.c'\" unpacked with wrong size!
  428. fi
  429. # end of 'Src/msstuff.c'
  430. fi
  431. if test -f 'Src/xsimage.c' -a "${1}" != "-c" ; then 
  432.   echo shar: Will not clobber existing file \"'Src/xsimage.c'\"
  433. else
  434. echo shar: Extracting \"'Src/xsimage.c'\" \(8825 characters\)
  435. sed "s/^X//" >'Src/xsimage.c' <<'END_OF_FILE'
  436. X/* xsimage.c - xscheme memory image save/restore functions */
  437. X/*    Copyright (c) 1988, by David Michael Betz
  438. X    All Rights Reserved
  439. X    Permission is granted for unrestricted non-commercial use    */
  440. X
  441. X#include "xscheme.h"
  442. X
  443. X/* virtual machine registers */
  444. Xextern LVAL xlfun;        /* current function */
  445. Xextern LVAL xlenv;        /* current environment */
  446. Xextern LVAL xlval;        /* value of most recent instruction */
  447. X
  448. X/* stack limits */
  449. Xextern LVAL *xlstkbase;        /* base of value stack */
  450. Xextern LVAL *xlstktop;        /* top of value stack */
  451. X
  452. X/* node space */
  453. Xextern NSEGMENT *nsegments;    /* list of node segments */
  454. X
  455. X/* vector (and string) space */
  456. Xextern VSEGMENT *vsegments;    /* list of vector segments */
  457. Xextern LVAL *vfree;        /* next free location in vector space */
  458. Xextern LVAL *vtop;        /* top of vector space */
  459. X
  460. X/* global variables */
  461. Xextern LVAL obarray,eof_object,default_object;
  462. Xextern jmp_buf top_level;
  463. Xextern FUNDEF funtab[];
  464. X
  465. X/* local variables */
  466. Xstatic OFFTYPE off,foff;
  467. Xstatic FILE *fp;
  468. X
  469. X/* external routines */
  470. Xextern FILE *osbopen();
  471. X
  472. X/* forward declarations */
  473. XOFFTYPE readptr();
  474. XOFFTYPE cvoptr();
  475. XLVAL cviptr();
  476. X
  477. X/* xlisave - save the memory image */
  478. Xint xlisave(fname)
  479. X  char *fname;
  480. X{
  481. X    unsigned char *cp;
  482. X    NSEGMENT *nseg;
  483. X    int size,n;
  484. X    LVAL p,*vp;
  485. X
  486. X    /* open the output file */
  487. X    if ((fp = osbopen(fname,"w")) == NULL)
  488. X    return (FALSE);
  489. X
  490. X    /* first call the garbage collector to clean up memory */
  491. X    gc();
  492. X
  493. X    /* write out the stack size */
  494. X    writeptr((OFFTYPE)(xlstktop-xlstkbase));
  495. X
  496. X    /* write out the *obarray* symbol and various constants */
  497. X    writeptr(cvoptr(obarray));
  498. X    writeptr(cvoptr(eof_object));
  499. X    writeptr(cvoptr(default_object));
  500. X
  501. X    /* setup the initial file offsets */
  502. X    off = foff = (OFFTYPE)2;
  503. X
  504. X    /* write out all nodes that are still in use */
  505. X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
  506. X    p = &nseg->ns_data[0];
  507. X    n = nseg->ns_size;
  508. X    for (; --n >= 0; ++p, off += sizeof(NODE))
  509. X        switch (ntype(p)) {
  510. X        case FREE:
  511. X        break;
  512. X        case CONS:
  513. X        case CLOSURE:
  514. X        case METHOD:
  515. X        case PROMISE:
  516. X        case ENV:
  517. X        setoffset();
  518. X        osbputc(p->n_type,fp);
  519. X        writeptr(cvoptr(car(p)));
  520. X        writeptr(cvoptr(cdr(p)));
  521. X        foff += sizeof(NODE);
  522. X        break;
  523. X        case SYMBOL:
  524. X        case OBJECT:
  525. X        case VECTOR:
  526. X        case CODE:
  527. X        case CONTINUATION:
  528. X        setoffset();
  529. X        osbputc(p->n_type,fp);
  530. X        size = getsize(p);
  531. X        writeptr((OFFTYPE)size);
  532. X        for (vp = p->n_vdata; --size >= 0; )
  533. X            writeptr(cvoptr(*vp++));
  534. X        foff += sizeof(NODE);
  535. X        break;
  536. X        case STRING:
  537. X        setoffset();
  538. X        osbputc(p->n_type,fp);
  539. X        size = getslength(p);
  540. X        writeptr((OFFTYPE)size);
  541. X        for (cp = getstring(p); --size >= 0; )
  542. X            osbputc(*cp++,fp);
  543. X        foff += sizeof(NODE);
  544. X        break;
  545. X        default:
  546. X        setoffset();
  547. X        writenode(p);
  548. X        foff += sizeof(NODE);
  549. X        break;
  550. X        }
  551. X    }
  552. X
  553. X    /* write the terminator */
  554. X    osbputc(FREE,fp);
  555. X    writeptr((OFFTYPE)0);
  556. X
  557. X    /* close the output file */
  558. X    osclose(fp);
  559. X
  560. X    /* return successfully */
  561. X    return (TRUE);
  562. X}
  563. X
  564. X/* xlirestore - restore a saved memory image */
  565. Xint xlirestore(fname)
  566. X  char *fname;
  567. X{
  568. X    LVAL *getvspace();
  569. X    unsigned int ssize;
  570. X    unsigned char *cp;
  571. X    int size,type;
  572. X    LVAL p,*vp;
  573. X
  574. X    /* open the file */
  575. X    if ((fp = osbopen(fname,"r")) == NULL)
  576. X    return (FALSE);
  577. X
  578. X    /* free the old memory image */
  579. X    freeimage();
  580. X
  581. X    /* read the stack size */
  582. X    ssize = (unsigned int)readptr();
  583. X
  584. X    /* allocate memory for the workspace */
  585. X    xlminit(ssize);
  586. X
  587. X    /* read the *obarray* symbol and various constants */
  588. X    obarray = cviptr(readptr());
  589. X    eof_object = cviptr(readptr());
  590. X    default_object = cviptr(readptr());
  591. X    
  592. X    /* read each node */
  593. X    for (off = (OFFTYPE)2; (type = osbgetc(fp)) >= 0; )
  594. X    switch (type) {
  595. X    case FREE:
  596. X        if ((off = readptr()) == (OFFTYPE)0)
  597. X        goto done;
  598. X        break;
  599. X    case CONS:
  600. X    case CLOSURE:
  601. X    case METHOD:
  602. X    case PROMISE:
  603. X    case ENV:
  604. X        p = cviptr(off);
  605. X        p->n_type = type;
  606. X        rplaca(p,cviptr(readptr()));
  607. X        rplacd(p,cviptr(readptr()));
  608. X        off += sizeof(NODE);
  609. X        break;
  610. X    case SYMBOL:
  611. X    case OBJECT:
  612. X    case VECTOR:
  613. X    case CODE:
  614. X    case CONTINUATION:
  615. X        p = cviptr(off);
  616. X        p->n_type = type;
  617. X        p->n_vsize = size = (int)readptr();
  618. X        p->n_vdata = getvspace(p,size);
  619. X        for (vp = p->n_vdata; --size >= 0; )
  620. X        *vp++ = cviptr(readptr());
  621. X        off += sizeof(NODE);
  622. X        break;
  623. X    case STRING:
  624. X        p = cviptr(off);
  625. X        p->n_type = type;
  626. X        p->n_vsize = size = (int)readptr();
  627. X        p->n_vdata = getvspace(p,btow_size(size));
  628. X        for (cp = getstring(p); --size >= 0; )
  629. X        *cp++ = osbgetc(fp);
  630. X        off += sizeof(NODE);
  631. X        break;
  632. X    case PORT:
  633. X        p = cviptr(off);
  634. X        readnode(type,p);
  635. X        setfile(p,NULL);
  636. X        off += sizeof(NODE);
  637. X        break;
  638. X    case SUBR:
  639. X    case XSUBR:
  640. X        p = cviptr(off);
  641. X        readnode(type,p);
  642. X        p->n_subr = funtab[getoffset(p)].fd_subr;
  643. X        off += sizeof(NODE);
  644. X        break;
  645. X    default:
  646. X        readnode(type,cviptr(off));
  647. X        off += sizeof(NODE);
  648. X        break;
  649. X    }
  650. Xdone:
  651. X
  652. X    /* close the input file */
  653. X    osclose(fp);
  654. X
  655. X    /* collect to initialize the free space */
  656. X    gc();
  657. X
  658. X    /* lookup all of the symbols the interpreter uses */
  659. X    xlsymbols();
  660. X
  661. X    /* return successfully */
  662. X    return (TRUE);
  663. X}
  664. X
  665. X/* freeimage - free the current memory image */
  666. XLOCAL freeimage()
  667. X{
  668. X    NSEGMENT *nextnseg;
  669. X    VSEGMENT *nextvseg;
  670. X    FILE *fp;
  671. X    LVAL p;
  672. X    int n;
  673. X
  674. X    /* close all open ports and free each node segment */
  675. X    for (; nsegments != NULL; nsegments = nextnseg) {
  676. X    nextnseg = nsegments->ns_next;
  677. X    p = &nsegments->ns_data[0];
  678. X    n = nsegments->ns_size;
  679. X    for (; --n >= 0; ++p)
  680. X        switch (ntype(p)) {
  681. X        case PORT:
  682. X        if ((fp = getfile(p))
  683. X         && (fp != stdin && fp != stdout && fp != stderr))
  684. X            osclose(getfile(p));
  685. X        break;
  686. X        }
  687. X    free(nsegments);
  688. X    }
  689. X
  690. X    /* free each vector segment */
  691. X    for (; vsegments != NULL; vsegments = nextvseg) {
  692. X    nextvseg = vsegments->vs_next;
  693. X    free(vsegments);
  694. X    }
  695. X    
  696. X    /* free the stack */
  697. X    if (xlstkbase)
  698. X    free(xlstkbase);
  699. X}
  700. X
  701. X/* setoffset - output a positioning command if nodes have been skipped */
  702. XLOCAL setoffset()
  703. X{
  704. X    if (off != foff) {
  705. X    osbputc(FREE,fp);
  706. X    writeptr(off);
  707. X    foff = off;
  708. X    }
  709. X}
  710. X
  711. X/* writenode - write a node to a file */
  712. XLOCAL writenode(node)
  713. X  LVAL node;
  714. X{
  715. X    char *p = (char *)&node->n_info;
  716. X    int n = sizeof(union ninfo);
  717. X    osbputc(node->n_type,fp);
  718. X    while (--n >= 0)
  719. X    osbputc(*p++,fp);
  720. X}
  721. X
  722. X/* writeptr - write a pointer to a file */
  723. XLOCAL writeptr(off)
  724. X  OFFTYPE off;
  725. X{
  726. X    char *p = (char *)&off;
  727. X    int n = sizeof(OFFTYPE);
  728. X    while (--n >= 0)
  729. X    osbputc(*p++,fp);
  730. X}
  731. X
  732. X/* readnode - read a node */
  733. XLOCAL readnode(type,node)
  734. X  int type; LVAL node;
  735. X{
  736. X    char *p = (char *)&node->n_info;
  737. X    int n = sizeof(union ninfo);
  738. X    node->n_type = type;
  739. X    while (--n >= 0)
  740. X    *p++ = osbgetc(fp);
  741. X}
  742. X
  743. X/* readptr - read a pointer */
  744. XLOCAL OFFTYPE readptr()
  745. X{
  746. X    OFFTYPE off;
  747. X    char *p = (char *)&off;
  748. X    int n = sizeof(OFFTYPE);
  749. X    while (--n >= 0)
  750. X    *p++ = osbgetc(fp);
  751. X    return (off);
  752. X}
  753. X
  754. X/* cviptr - convert a pointer on input */
  755. XLOCAL LVAL cviptr(o)
  756. X  OFFTYPE o;
  757. X{
  758. X    NSEGMENT *newnsegment(),*nseg;
  759. X    OFFTYPE off = (OFFTYPE)2;
  760. X    OFFTYPE nextoff;
  761. X
  762. X    /* check for nil and small fixnums */
  763. X    if (o == (OFFTYPE)0 || (o & 1) == 1)
  764. X    return ((LVAL)o);
  765. X
  766. X    /* compute a pointer for this offset */
  767. X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
  768. X    nextoff = off + (OFFTYPE)(nseg->ns_size * sizeof(NODE));
  769. X    if (o >= off && o < nextoff)
  770. X        return ((LVAL)((OFFTYPE)&nseg->ns_data[0] + o - off));
  771. X    off = nextoff;
  772. X    }
  773. X
  774. X    /* create new segments if necessary */
  775. X    for (;;) {
  776. X
  777. X    /* create the next segment */
  778. X    if ((nseg = newnsegment(NSSIZE)) == NULL)
  779. X        xlfatal("insufficient memory - segment");
  780. X
  781. X    /* check to see if the offset is in this segment */
  782. X    nextoff = off + (OFFTYPE)(nseg->ns_size * sizeof(NODE));
  783. X    if (o >= off && o < nextoff)
  784. X        return ((LVAL)((OFFTYPE)&nseg->ns_data[0] + o - off));
  785. X    off = nextoff;
  786. X    }
  787. X}
  788. X
  789. X/* cvoptr - convert a pointer on output */
  790. XLOCAL OFFTYPE cvoptr(p)
  791. X  LVAL p;
  792. X{
  793. X    OFFTYPE off = (OFFTYPE)2;
  794. X    NSEGMENT *nseg;
  795. X
  796. X    /* check for nil and small fixnums */
  797. X    if (p == NIL || !ispointer(p))
  798. X    return ((OFFTYPE)p);
  799. X
  800. X    /* compute an offset for this pointer */
  801. X    for (nseg = nsegments; nseg != NULL; nseg = nseg->ns_next) {
  802. X    if (INSEGMENT(p,nseg))
  803. X        return (off + ((OFFTYPE)p - (OFFTYPE)&nseg->ns_data[0]));
  804. X    off += (OFFTYPE)(nseg->ns_size * sizeof(NODE));
  805. X    }
  806. X
  807. X    /* pointer not within any segment */
  808. X    xlerror("bad pointer found during image save",p);
  809. X}
  810. X
  811. X/* getvspace - allocate vector space */
  812. XLOCAL LVAL *getvspace(node,size)
  813. X  LVAL node; unsigned int size;
  814. X{
  815. X    LVAL *p;
  816. X    ++size; /* space for the back pointer */
  817. X    if (vfree + size >= vtop) {
  818. X    makevmemory(size);
  819. X    if (vfree + size >= vtop)
  820. X        xlfatal("insufficient vector space");
  821. X    }
  822. X    p = vfree;
  823. X    vfree += size;
  824. X    *p++ = node;
  825. X    return (p);
  826. X}
  827. END_OF_FILE
  828. if test 8825 -ne `wc -c <'Src/xsimage.c'`; then
  829.     echo shar: \"'Src/xsimage.c'\" unpacked with wrong size!
  830. fi
  831. # end of 'Src/xsimage.c'
  832. fi
  833. if test -f 'Src/xsint.c' -a "${1}" != "-c" ; then 
  834.   echo shar: Will not clobber existing file \"'Src/xsint.c'\"
  835. else
  836. echo shar: Extracting \"'Src/xsint.c'\" \(10297 characters\)
  837. sed "s/^X//" >'Src/xsint.c' <<'END_OF_FILE'
  838. X/* xsint.c - xscheme bytecode interpreter */
  839. X/*    Copyright (c) 1988, by David Michael Betz
  840. X    All Rights Reserved
  841. X    Permission is granted for unrestricted non-commercial use    */
  842. X
  843. X#include "xscheme.h"
  844. X#include "xsbcode.h"
  845. X
  846. X/* sample rate (instructions per sample) */
  847. X#define SRATE    1000
  848. X
  849. X/* macros to get the address of the code string for a code object */
  850. X#define getcodestr(x) ((unsigned char *)getstring(getbcode(x)))
  851. X
  852. X/* globals */
  853. Xint trace=FALSE;    /* trace enable */
  854. Xint xlargc;        /* argument count */
  855. Xjmp_buf bc_dispatch;    /* bytecode dispatcher */
  856. X
  857. X/* external variables */
  858. Xextern LVAL xlfun,xlenv,xlval;
  859. Xextern LVAL s_stdin,s_stdout,s_unbound;
  860. Xextern LVAL s_unassigned,default_object,true;
  861. X
  862. X/* external routines */
  863. Xextern LVAL xadd(),xsub(),xmul(),xdiv(),xlss(),xeql(),xgtr();
  864. X
  865. X/* local variables */
  866. Xstatic unsigned char *base,*pc;
  867. Xstatic int sample=SRATE;
  868. X
  869. X/* xtraceon - built-in function 'trace-on' */
  870. XLVAL xtraceon()
  871. X{
  872. X    xllastarg()
  873. X    trace = TRUE;
  874. X    return (NIL);
  875. X}
  876. X
  877. X/* xtraceoff - built-in function 'trace-off' */
  878. XLVAL xtraceoff()
  879. X{
  880. X    xllastarg()
  881. X    trace = FALSE;
  882. X    return (NIL);
  883. X}
  884. X
  885. X/* xlexecute - execute byte codes */
  886. Xxlexecute(fun)
  887. X  LVAL fun;
  888. X{
  889. X    LVAL findvar(),make_continuation();
  890. X    register LVAL tmp;
  891. X    register unsigned int i;
  892. X    register int k;
  893. X    int off;
  894. X
  895. X    /* initialize the registers */
  896. X    xlfun = getcode(fun);
  897. X    xlenv = getenv(fun);
  898. X    xlval = NIL;
  899. X
  900. X    /* initialize the argument count */
  901. X    xlargc = 0;
  902. X
  903. X    /* set the initial pc */
  904. X    base = pc = getcodestr(xlfun);
  905. X
  906. X    /* setup a target for the error handler */
  907. X    setjmp(bc_dispatch);
  908. X    
  909. X    /* execute the code */
  910. X    for (;;) {
  911. X
  912. X    /* check for control codes */
  913. X    if (--sample <= 0) {
  914. X        sample = SRATE;
  915. X        oscheck();
  916. X    }
  917. X
  918. X    /* print the trace information */
  919. X    if (trace)
  920. X        decode_instruction(curoutput(),xlfun,(int)(pc-base),xlenv);
  921. X
  922. X    /* execute the next bytecode instruction */
  923. X    switch (*pc++) {
  924. X    case OP_BRT:
  925. X        i = *pc++ << 8; i |= *pc++;
  926. X        if (xlval) pc = base + i;
  927. X        break;
  928. X    case OP_BRF:
  929. X        i = *pc++ << 8; i |= *pc++;
  930. X        if (!xlval) pc = base + i;
  931. X        break;
  932. X    case OP_BR:
  933. X        i = *pc++ << 8; i |= *pc++;
  934. X        pc = base + i;
  935. X        break;
  936. X    case OP_LIT:
  937. X        xlval = getelement(xlfun,*pc++);
  938. X        break;
  939. X    case OP_GREF:
  940. X        tmp = getelement(xlfun,*pc++);
  941. X        if ((xlval = getvalue(tmp)) == s_unbound) {
  942. X            if (xlval = getvalue(xlenter("*UNBOUND-HANDLER*"))) {
  943. X            oscheck();
  944. X            pc -= 2; /* backup the pc */
  945. X            tmp = make_continuation();
  946. X            check(2);
  947. X            push(tmp);
  948. X            push(getelement(xlfun,pc[1]));
  949. X            xlargc = 2;
  950. X            xlapply();
  951. X            }
  952. X            else
  953. X            xlerror("unbound variable",tmp);
  954. X        }
  955. X        break;
  956. X    case OP_GSET:
  957. X        setvalue(getelement(xlfun,*pc++),xlval);
  958. X        break;
  959. X    case OP_EREF:
  960. X        k = *pc++;
  961. X        tmp = xlenv;
  962. X        while (--k >= 0) tmp = cdr(tmp);
  963. X        xlval = getelement(car(tmp),*pc++);
  964. X        break;
  965. X    case OP_ESET:
  966. X        k = *pc++;
  967. X        tmp = xlenv;
  968. X        while (--k >= 0) tmp = cdr(tmp);
  969. X        setelement(car(tmp),*pc++,xlval);
  970. X        break;
  971. X    case OP_AREF:
  972. X        i = *pc++;
  973. X        tmp = xlval;
  974. X        if (!envp(tmp)) badargtype(tmp);
  975. X        if ((tmp = findvar(tmp,getelement(xlfun,i),&off)) != NIL)
  976. X            xlval = getelement(car(tmp),off);
  977. X        else
  978. X            xlval = s_unassigned;
  979. X        break;
  980. X    case OP_ASET:
  981. X        i = *pc++;
  982. X        tmp = pop();
  983. X        if (!envp(tmp)) badargtype(tmp);
  984. X        if ((tmp = findvar(tmp,getelement(xlfun,i),&off)) == NIL)
  985. X            xlerror("no binding for variable",getelement(xlfun,i));
  986. X        setelement(car(tmp),off,xlval);
  987. X        break;
  988. X    case OP_SAVE:    /* save a continuation */
  989. X        i = *pc++ << 8; i |= *pc++;
  990. X        check(3);
  991. X        push(cvsfixnum((FIXTYPE)i));
  992. X        push(xlfun);
  993. X        push(xlenv);
  994. X        break;
  995. X    case OP_CALL:    /* call a function (or built-in) */
  996. X        xlargc = *pc++;    /* get argument count */
  997. X        xlapply();    /* apply the function */
  998. X        break;
  999. X    case OP_RETURN:    /* return to the continuation on the stack */
  1000. X        xlreturn();
  1001. X        break;
  1002. X    case OP_FRAME:    /* create an environment frame */
  1003. X        i = *pc++;    /* get the frame size */
  1004. X        xlenv = newframe(xlenv,i);
  1005. X        setelement(car(xlenv),0,getvnames(xlfun));
  1006. X        break;
  1007. X    case OP_MVARG:    /* move required argument to frame slot */
  1008. X        i = *pc++;    /* get the slot number */
  1009. X        if (--xlargc < 0)
  1010. X            xlfail("too few arguments");
  1011. X        setelement(car(xlenv),i,pop());
  1012. X        break;
  1013. X    case OP_MVOARG:    /* move optional argument to frame slot */
  1014. X        i = *pc++;    /* get the slot number */
  1015. X        if (xlargc > 0) {
  1016. X            setelement(car(xlenv),i,pop());
  1017. X            --xlargc;
  1018. X        }
  1019. X        else
  1020. X            setelement(car(xlenv),i,default_object);
  1021. X        break;
  1022. X    case OP_MVRARG:    /* build rest argument and move to frame slot */
  1023. X        i = *pc++;    /* get the slot number */
  1024. X        for (xlval = NIL, k = xlargc; --k >= 0; )
  1025. X            xlval = cons(xlsp[k],xlval);
  1026. X        setelement(car(xlenv),i,xlval);
  1027. X        drop(xlargc);
  1028. X        break;
  1029. X    case OP_ALAST:    /* make sure there are no more arguments */
  1030. X        if (xlargc > 0)
  1031. X            xlfail("too many arguments");
  1032. X        break;
  1033. X    case OP_T:
  1034. X        xlval = true;
  1035. X        break;
  1036. X    case OP_NIL:
  1037. X        xlval = NIL;
  1038. X        break;
  1039. X    case OP_PUSH:
  1040. X        cpush(xlval);
  1041. X        break;
  1042. X    case OP_CLOSE:
  1043. X        if (!codep(xlval)) badargtype(xlval);
  1044. X        xlval = cvclosure(xlval,xlenv);
  1045. X        break;
  1046. X    case OP_DELAY:
  1047. X        if (!codep(xlval)) badargtype(xlval);
  1048. X        xlval = cvpromise(xlval,xlenv);
  1049. X        break;
  1050. X    case OP_ATOM:
  1051. X        xlval = (atom(xlval) ? true : NIL);
  1052. X        break;
  1053. X    case OP_EQ:
  1054. X        xlval = (xlval == pop() ? true : NIL);
  1055. X        break;
  1056. X    case OP_NULL:
  1057. X        xlval = (xlval ? NIL : true);
  1058. X        break;
  1059. X    case OP_CONS:
  1060. X        xlval = cons(xlval,pop());
  1061. X        break;
  1062. X    case OP_CAR:
  1063. X        if (!listp(xlval)) badargtype(xlval);
  1064. X        xlval = (xlval ? car(xlval) : NIL);
  1065. X        break;
  1066. X    case OP_CDR:
  1067. X        if (!listp(xlval)) badargtype(xlval);
  1068. X        xlval = (xlval ? cdr(xlval) : NIL);
  1069. X        break;
  1070. X    case OP_SETCAR:
  1071. X        if (!consp(xlval)) badargtype(xlval);
  1072. X        rplaca(xlval,pop());
  1073. X        break;
  1074. X    case OP_SETCDR:
  1075. X        if (!consp(xlval)) badargtype(xlval);
  1076. X        rplacd(xlval,pop());
  1077. X        break;
  1078. X    case OP_ADD:
  1079. X        tmp = pop();
  1080. X        if (fixp(xlval) && fixp(tmp))
  1081. X            xlval = cvfixnum(getfixnum(xlval) + getfixnum(tmp));
  1082. X        else {
  1083. X            push(tmp); push(xlval); xlargc = 2;
  1084. X            xlval = xadd();
  1085. X        }
  1086. X        break;
  1087. X    case OP_SUB:
  1088. X        tmp = pop();
  1089. X        if (fixp(xlval) && fixp(tmp))
  1090. X            xlval = cvfixnum(getfixnum(xlval) - getfixnum(tmp));
  1091. X        else {
  1092. X            push(tmp); push(xlval); xlargc = 2;
  1093. X            xlval = xsub();
  1094. X        }
  1095. X        break;
  1096. X    case OP_MUL:
  1097. X        tmp = pop();
  1098. X        if (fixp(xlval) && fixp(tmp))
  1099. X            xlval = cvfixnum(getfixnum(xlval) * getfixnum(tmp));
  1100. X        else {
  1101. X            push(tmp); push(xlval); xlargc = 2;
  1102. X            xlval = xmul();
  1103. X        }
  1104. X        break;
  1105. X    case OP_QUO:
  1106. X        tmp = pop();
  1107. X        if (fixp(xlval) && fixp(tmp))
  1108. X            xlval = cvfixnum(getfixnum(xlval) / getfixnum(tmp));
  1109. X        else if (fixp(xlval))
  1110. X            badargtype(tmp);
  1111. X        else
  1112. X            badargtype(xlval);
  1113. X        break;
  1114. X    case OP_LSS:
  1115. X        tmp = pop();
  1116. X        if (fixp(xlval) && fixp(tmp))
  1117. X            xlval = (getfixnum(xlval) < getfixnum(tmp) ? true : NIL);
  1118. X        else {
  1119. X            push(tmp); push(xlval); xlargc = 2;
  1120. X            xlval = xlss();
  1121. X        }
  1122. X        break;
  1123. X    case OP_EQL:
  1124. X        tmp = pop();
  1125. X        if (fixp(xlval) && fixp(tmp))
  1126. X            xlval = (getfixnum(xlval) == getfixnum(tmp) ? true : NIL);
  1127. X        else {
  1128. X            push(tmp); push(xlval); xlargc = 2;
  1129. X            xlval = xeql();
  1130. X        }
  1131. X        break;
  1132. X    case OP_GTR:
  1133. X        tmp = pop();
  1134. X        if (fixp(xlval) && fixp(tmp))
  1135. X            xlval = (getfixnum(xlval) > getfixnum(tmp) ? true : NIL);
  1136. X        else {
  1137. X            push(tmp); push(xlval); xlargc = 2;
  1138. X            xlval = xgtr();
  1139. X        }
  1140. X        break;
  1141. X    default:
  1142. X        xlerror("bad opcode",cvsfixnum((FIXTYPE)*--pc));
  1143. X        break;
  1144. X    }
  1145. X    }
  1146. X}
  1147. X
  1148. X/* findvar - find a variable in an environment */
  1149. XLOCAL LVAL findvar(env,var,poff)
  1150. X  LVAL env,var; int *poff;
  1151. X{
  1152. X    LVAL names;
  1153. X    int off;
  1154. X    for (; env != NIL; env = cdr(env)) {
  1155. X    names = getelement(car(env),0);
  1156. X    for (off = 1; names != NIL; ++off, names = cdr(names))
  1157. X        if (var == car(names)) {
  1158. X        *poff = off;
  1159. X        return (env);
  1160. X        }
  1161. X    }
  1162. X    return (NIL);
  1163. X}
  1164. X
  1165. X/* xlapply - apply a function to arguments */
  1166. X/*    The function should be in xlval and the arguments should
  1167. X    be on the stack.  The number of arguments should be in xlargc.
  1168. X*/
  1169. Xxlapply()
  1170. X{
  1171. X    LVAL tmp;
  1172. X
  1173. X    /* check for null function */
  1174. X    if (null(xlval))
  1175. X    badfuntype(xlval);
  1176. X
  1177. X    /* dispatch on function type */
  1178. X    switch (ntype(xlval)) {
  1179. X    case SUBR:
  1180. X    xlval = (*getsubr(xlval))();
  1181. X    xlreturn();
  1182. X    break;
  1183. X    case XSUBR:
  1184. X    (*getsubr(xlval))();
  1185. X    break;
  1186. X    case CLOSURE:
  1187. X    xlfun = getcode(xlval);
  1188. X    xlenv = getenv(xlval);
  1189. X    base = pc = getcodestr(xlfun);
  1190. X    break;
  1191. X    case OBJECT:
  1192. X    xlsend(xlval,xlgasymbol());
  1193. X    break;
  1194. X    case METHOD:
  1195. X    xlfun = getcode(xlval);
  1196. X    xlenv = cons(top(),getenv(xlval));
  1197. X    base = pc = getcodestr(xlfun);
  1198. X    break;
  1199. X    case CONTINUATION:
  1200. X    tmp = xlgetarg();
  1201. X    xllastarg();
  1202. X    restore_continuation();
  1203. X    xlval = tmp;
  1204. X    xlreturn();
  1205. X    break;
  1206. X    default:
  1207. X    badfuntype(xlval);
  1208. X    }
  1209. X}
  1210. X
  1211. X/* xlreturn - return to a continuation on the stack */
  1212. Xxlreturn()
  1213. X{
  1214. X    LVAL tmp;
  1215. X    
  1216. X    /* restore the enviroment and the continuation function */
  1217. X    xlenv = pop();
  1218. X    tmp = pop();
  1219. X    
  1220. X    /* dispatch on the function type */
  1221. X    switch (ntype(tmp)) {
  1222. X    case CODE:
  1223. X        xlfun = tmp;
  1224. X        tmp = pop();
  1225. X    base = getcodestr(xlfun);
  1226. X    pc = base + (int)getsfixnum(tmp);
  1227. X    break;
  1228. X    case CSUBR:
  1229. X    (*getsubr(tmp))();
  1230. X    break;
  1231. X    default:
  1232. X    xlerror("bad continuation",tmp);
  1233. X    }
  1234. X}
  1235. X
  1236. X/* make_continuation - make a continuation */
  1237. XLOCAL LVAL make_continuation()
  1238. X{
  1239. X    LVAL cont,*src,*dst;
  1240. X    int size;
  1241. X
  1242. X    /* save a continuation on the stack */
  1243. X    check(3);
  1244. X    push(cvsfixnum((FIXTYPE)(pc - base)));
  1245. X    push(xlfun);
  1246. X    push(xlenv);
  1247. X
  1248. X    /* create and initialize a continuation object */
  1249. X    size = (int)(xlstktop - xlsp);
  1250. X    cont = newcontinuation(size);
  1251. X    for (src = xlsp, dst = &cont->n_vdata[0]; --size >= 0; )
  1252. X    *dst++ = *src++;
  1253. X    
  1254. X    /* return the continuation */
  1255. X    return (cont);
  1256. X}
  1257. X
  1258. X/* restore_continuation - restore a continuation to the stack */
  1259. X/*    The continuation should be in xlval.
  1260. X*/
  1261. XLOCAL restore_continuation()
  1262. X{
  1263. X    LVAL *src;
  1264. X    int size;
  1265. X    size = getsize(xlval);
  1266. X    for (src = &xlval->n_vdata[size], xlsp = xlstktop; --size >= 0; )
  1267. X    *--xlsp = *--src;
  1268. X}
  1269. X
  1270. X/* gc_protect - protect the state of the interpreter from the collector */
  1271. Xgc_protect(protected_fcn)
  1272. X  int (*protected_fcn)();
  1273. X{
  1274. X    int pcoff;
  1275. X    pcoff = pc - base;
  1276. X    (*protected_fcn)();
  1277. X    if (xlfun) {
  1278. X    base = getcodestr(xlfun);
  1279. X    pc = base + pcoff;
  1280. X    }
  1281. X}
  1282. X
  1283. X/* badfuntype - bad function error */
  1284. XLOCAL badfuntype(arg)
  1285. X  LVAL arg;
  1286. X{
  1287. X    xlerror("bad function type",arg);
  1288. X}
  1289. X
  1290. X/* badargtype - bad argument type error */
  1291. XLOCAL badargtype(arg)
  1292. X  LVAL arg;
  1293. X{
  1294. X    xlbadtype(arg);
  1295. X}
  1296. X
  1297. X/* xlstkover - value stack overflow */
  1298. Xxlstkover()
  1299. X{
  1300. X    xlabort("value stack overflow");
  1301. X}
  1302. END_OF_FILE
  1303. if test 10297 -ne `wc -c <'Src/xsint.c'`; then
  1304.     echo shar: \"'Src/xsint.c'\" unpacked with wrong size!
  1305. fi
  1306. # end of 'Src/xsint.c'
  1307. fi
  1308. if test -f 'Src/xsobj.c' -a "${1}" != "-c" ; then 
  1309.   echo shar: Will not clobber existing file \"'Src/xsobj.c'\"
  1310. else
  1311. echo shar: Extracting \"'Src/xsobj.c'\" \(9292 characters\)
  1312. sed "s/^X//" >'Src/xsobj.c' <<'END_OF_FILE'
  1313. X/* xsobj.c - xscheme object-oriented programming support */
  1314. X/*    Copyright (c) 1988, by David Michael Betz
  1315. X    All Rights Reserved
  1316. X    Permission is granted for unrestricted non-commercial use    */
  1317. X
  1318. X#include "xscheme.h"
  1319. X
  1320. X/* external variables */
  1321. Xextern LVAL xlenv,xlval;
  1322. Xextern LVAL s_stdout;
  1323. X
  1324. X/* local variables */
  1325. Xstatic LVAL s_self,k_isnew;
  1326. Xstatic LVAL class,object;
  1327. X
  1328. X/* instance variable numbers for the class 'Class' */
  1329. X#define MESSAGES    2    /* list of messages */
  1330. X#define IVARS        3    /* list of instance variable names */
  1331. X#define CVARS        4    /* env containing class variables */
  1332. X#define SUPERCLASS    5    /* pointer to the superclass */
  1333. X#define IVARCNT        6    /* number of class instance variables */
  1334. X#define IVARTOTAL    7    /* total number of instance variables */
  1335. X
  1336. X/* number of instance variables for the class 'Class' */
  1337. X#define CLASSSIZE    6
  1338. X
  1339. X/* forward declarations */
  1340. XFORWARD LVAL entermsg();
  1341. XFORWARD LVAL copylists();
  1342. X
  1343. X/* xlsend - send a message to an object */
  1344. Xxlsend(obj,sym)
  1345. X  LVAL obj,sym;
  1346. X{
  1347. X    LVAL msg,cls,p;
  1348. X
  1349. X    /* look for the message in the class or superclasses */
  1350. X    for (cls = getclass(obj); cls; cls = getivar(cls,SUPERCLASS))
  1351. X    for (p = getivar(cls,MESSAGES); p; p = cdr(p))
  1352. X        if ((msg = car(p)) && car(msg) == sym) {
  1353. X        push(obj); ++xlargc; /* insert 'self' argument */
  1354. X        xlval = cdr(msg);    /* get the method */
  1355. X        xlapply();         /* invoke the method */
  1356. X        return;
  1357. X        }
  1358. X
  1359. X    /* message not found */
  1360. X    xlerror("no method for this message",sym);
  1361. X}
  1362. X
  1363. X/* xsendsuper - built-in function 'send-super' */
  1364. XLVAL xsendsuper()
  1365. X{
  1366. X    LVAL obj,sym,msg,cls,p;
  1367. X
  1368. X    /* get the message selector */
  1369. X    sym = xlgasymbol();
  1370. X    
  1371. X    /* find the 'self' object */
  1372. X    for (obj = xlenv; obj; obj = cdr(obj))
  1373. X    if (ntype(car(obj)) == OBJECT)
  1374. X        goto find_method;
  1375. X    xlerror("not in a method",sym);
  1376. X
  1377. Xfind_method:
  1378. X    /* get the message class and the 'self' object */
  1379. X    cls = getivar(getelement(car(cdr(obj)),0),SUPERCLASS);
  1380. X    obj = car(obj);
  1381. X    
  1382. X    /* look for the message in the class or superclasses */
  1383. X    for (; cls; cls = getivar(cls,SUPERCLASS))
  1384. X    for (p = getivar(cls,MESSAGES); p; p = cdr(p))
  1385. X        if ((msg = car(p)) && car(msg) == sym) {
  1386. X        push(obj); ++xlargc; /* insert 'self' argument */
  1387. X        xlval = cdr(msg);    /* get the method */
  1388. X        xlapply();         /* invoke the method */
  1389. X        return;
  1390. X        }
  1391. X
  1392. X    /* message not found */
  1393. X    xlerror("no method for this message",sym);
  1394. X}
  1395. X
  1396. X/* obisnew - default 'isnew' method */
  1397. XLVAL obisnew()
  1398. X{
  1399. X    LVAL self;
  1400. X    self = xlgaobject();
  1401. X    xllastarg();
  1402. X    return (self);
  1403. X}
  1404. X
  1405. X/* obclass - get the class of an object */
  1406. XLVAL obclass()
  1407. X{
  1408. X    LVAL self;
  1409. X    self = xlgaobject();
  1410. X    xllastarg();
  1411. X    return (getclass(self));
  1412. X}
  1413. X
  1414. X/* obshow - show the instance variables of an object */
  1415. XLVAL obshow()
  1416. X{
  1417. X    LVAL self,fptr,cls,names;
  1418. X    int maxi,i;
  1419. X
  1420. X    /* get self and the file pointer */
  1421. X    self = xlgaobject();
  1422. X    fptr = (moreargs() ? xlgaoport() : getvalue(s_stdout));
  1423. X    xllastarg();
  1424. X
  1425. X    /* get the object's class */
  1426. X    cls = getclass(self);
  1427. X
  1428. X    /* print the object and class */
  1429. X    xlputstr(fptr,"Object is ");
  1430. X    xlprin1(self,fptr);
  1431. X    xlputstr(fptr,", Class is ");
  1432. X    xlprin1(cls,fptr);
  1433. X    xlterpri(fptr);
  1434. X
  1435. X    /* print the object's instance variables */
  1436. X    names = cdr(getivar(cls,IVARS));
  1437. X    maxi = getivcnt(cls,IVARTOTAL)+1;
  1438. X    for (i = 2; i <= maxi; ++i) {
  1439. X    xlputstr(fptr,"  ");
  1440. X    xlprin1(car(names),fptr);
  1441. X    xlputstr(fptr," = ");
  1442. X    xlprin1(getivar(self,i),fptr);
  1443. X    xlterpri(fptr);
  1444. X    names = cdr(names);
  1445. X    }
  1446. X
  1447. X    /* return the object */
  1448. X    return (self);
  1449. X}
  1450. X
  1451. X/* clnew - create a new object instance */
  1452. XLVAL clnew()
  1453. X{
  1454. X    LVAL self;
  1455. X
  1456. X    /* create a new object */
  1457. X    self = xlgaobject();
  1458. X    xlval = newobject(self,getivcnt(self,IVARTOTAL));
  1459. X
  1460. X    /* send the 'isnew' message */
  1461. X    xlsend(xlval,k_isnew);
  1462. X}
  1463. X
  1464. X/* clisnew - initialize a new class */
  1465. XLVAL clisnew()
  1466. X{
  1467. X    LVAL self,ivars,cvars,super;
  1468. X    int n;
  1469. X
  1470. X    /* get self, the ivars, cvars and superclass */
  1471. X    self = xlgaobject();
  1472. X    ivars = xlgalist();
  1473. X    cvars = (moreargs() ? xlgalist() : NIL);
  1474. X    super = (moreargs() ? xlgaobject() : object);
  1475. X    xllastarg();
  1476. X
  1477. X    /* create the class variable name list */
  1478. X    cpush(cons(xlenter("%%CLASS"),copylists(cvars,NIL)));
  1479. X    
  1480. X    /* create the class variable environment */
  1481. X    xlval = newframe(getivar(super,CVARS),listlength(xlval)+1);
  1482. X    setelement(car(xlval),0,pop());
  1483. X    setelement(car(xlval),1,self);
  1484. X    push(xlval);
  1485. X
  1486. X    /* store the instance and class variable lists and the superclass */
  1487. X    setivar(self,IVARS,copylists(getivar(super,IVARS),ivars));
  1488. X    setivar(self,CVARS,pop());
  1489. X    setivar(self,SUPERCLASS,super);
  1490. X
  1491. X    /* compute the instance variable count */
  1492. X    n = listlength(ivars);
  1493. X    setivar(self,IVARCNT,cvfixnum((FIXTYPE)n));
  1494. X    n += getivcnt(super,IVARTOTAL);
  1495. X    setivar(self,IVARTOTAL,cvfixnum((FIXTYPE)n));
  1496. X
  1497. X    /* return the new class object */
  1498. X    return (self);
  1499. X}
  1500. X
  1501. X/* clanswer - define a method for answering a message */
  1502. XLVAL clanswer()
  1503. X{
  1504. X    extern LVAL xlfunction();
  1505. X    LVAL self,msg,fargs,code,mptr;
  1506. X
  1507. X    /* message symbol, formal argument list and code */
  1508. X    self = xlgaobject();
  1509. X    msg = xlgasymbol();
  1510. X    fargs = xlgetarg();
  1511. X    code = xlgalist();
  1512. X    xllastarg();
  1513. X
  1514. X    /* make a new message list entry */
  1515. X    mptr = entermsg(self,msg);
  1516. X
  1517. X    /* add 'self' to the argument list */
  1518. X    cpush(cons(s_self,fargs));
  1519. X
  1520. X    /* extend the class variable environment with the instance variables */
  1521. X    xlval = newframe(getivar(self,CVARS),1);
  1522. X    setelement(car(xlval),0,getivar(self,IVARS));
  1523. X    
  1524. X    /* compile and store the method */
  1525. X    xlval = xlfunction(msg,top(),code,xlval);
  1526. X    rplacd(mptr,cvmethod(xlval,getivar(self,CVARS)));
  1527. X    drop(1);
  1528. X
  1529. X    /* return the object */
  1530. X    return (self);
  1531. X}
  1532. X
  1533. X/* addivar - enter an instance variable */
  1534. XLOCAL addivar(cls,var)
  1535. X  LVAL cls; char *var;
  1536. X{
  1537. X    setivar(cls,IVARS,cons(xlenter(var),getivar(cls,IVARS)));
  1538. X}
  1539. X
  1540. X/* addmsg - add a message to a class */
  1541. XLOCAL addmsg(cls,msg,fname)
  1542. X  LVAL cls; char *msg,*fname;
  1543. X{
  1544. X    LVAL mptr;
  1545. X
  1546. X    /* enter the message selector */
  1547. X    mptr = entermsg(cls,xlenter(msg));
  1548. X
  1549. X    /* store the method for this message */
  1550. X    rplacd(mptr,getvalue(xlenter(fname)));
  1551. X}
  1552. X
  1553. X/* entermsg - add a message to a class */
  1554. XLOCAL LVAL entermsg(cls,msg)
  1555. X  LVAL cls,msg;
  1556. X{
  1557. X    LVAL lptr,mptr;
  1558. X
  1559. X    /* lookup the message */
  1560. X    for (lptr = getivar(cls,MESSAGES); lptr; lptr = cdr(lptr))
  1561. X    if (car(mptr = car(lptr)) == msg)
  1562. X        return (mptr);
  1563. X
  1564. X    /* allocate a new message entry if one wasn't found */
  1565. X    cpush(cons(msg,NIL));
  1566. X    setivar(cls,MESSAGES,cons(top(),getivar(cls,MESSAGES)));
  1567. X
  1568. X    /* return the symbol node */
  1569. X    return (pop());
  1570. X}
  1571. X
  1572. X/* getivcnt - get the number of instance variables for a class */
  1573. XLOCAL int getivcnt(cls,ivar)
  1574. X  LVAL cls; int ivar;
  1575. X{
  1576. X    LVAL cnt;
  1577. X    if ((cnt = getivar(cls,ivar)) == NIL || !fixp(cnt))
  1578. X    xlerror("bad value for instance variable count",cnt);
  1579. X    return ((int)getfixnum(cnt));
  1580. X}
  1581. X
  1582. X/* copylist - make a copy of a list */
  1583. XLOCAL LVAL copylists(list1,list2)
  1584. X  LVAL list1,list2;
  1585. X{
  1586. X    LVAL last,next;
  1587. X    
  1588. X    /* initialize */
  1589. X    cpush(NIL); last = NIL;
  1590. X    
  1591. X    /* copy the first list */
  1592. X    for (; consp(list1); list1 = cdr(list1)) {
  1593. X    next = cons(car(list1),NIL);
  1594. X    if (last) rplacd(last,next);
  1595. X    else settop(next);
  1596. X    last = next;
  1597. X    }
  1598. X    
  1599. X    /* append the second list */
  1600. X    for (; consp(list2); list2 = cdr(list2)) {
  1601. X    next = cons(car(list2),NIL);
  1602. X    if (last) rplacd(last,next);
  1603. X    else settop(next);
  1604. X    last = next;
  1605. X    }
  1606. X    return (pop());
  1607. X}
  1608. X
  1609. X/* listlength - find the length of a list */
  1610. XLOCAL int listlength(list)
  1611. X  LVAL list;
  1612. X{
  1613. X    int len;
  1614. X    for (len = 0; consp(list); len++)
  1615. X    list = cdr(list);
  1616. X    return (len);
  1617. X}
  1618. X
  1619. X/* obsymbols - initialize symbols */
  1620. Xobsymbols()
  1621. X{
  1622. X    /* enter the object related symbols */
  1623. X    s_self  = xlenter("SELF");
  1624. X    k_isnew = xlenter("ISNEW");
  1625. X
  1626. X    /* get the Object and Class symbol values */
  1627. X    object = getvalue(xlenter("OBJECT"));
  1628. X    class  = getvalue(xlenter("CLASS"));
  1629. X}
  1630. X
  1631. X/* xloinit - object function initialization routine */
  1632. Xxloinit()
  1633. X{
  1634. X    LVAL sym;
  1635. X    
  1636. X    /* create the 'Object' object */
  1637. X    sym = xlenter("OBJECT");
  1638. X    object = newobject(NIL,CLASSSIZE);
  1639. X    setvalue(sym,object);
  1640. X    setivar(object,IVARS,cons(xlenter("%%CLASS"),NIL));
  1641. X    setivar(object,IVARCNT,cvfixnum((FIXTYPE)0));
  1642. X    setivar(object,IVARTOTAL,cvfixnum((FIXTYPE)0));
  1643. X    addmsg(object,"ISNEW","%OBJECT-ISNEW");
  1644. X    addmsg(object,"CLASS","%OBJECT-CLASS");
  1645. X    addmsg(object,"SHOW","%OBJECT-SHOW");
  1646. X    
  1647. X    /* create the 'Class' object */
  1648. X    sym = xlenter("CLASS");
  1649. X    class = newobject(NIL,CLASSSIZE);
  1650. X    setvalue(sym,class);
  1651. X    addivar(class,"IVARTOTAL");    /* ivar number 6 */
  1652. X    addivar(class,"IVARCNT");    /* ivar number 5 */
  1653. X    addivar(class,"SUPERCLASS");/* ivar number 4 */
  1654. X    addivar(class,"CVARS");    /* ivar number 3 */
  1655. X    addivar(class,"IVARS");    /* ivar number 2 */
  1656. X    addivar(class,"MESSAGES");    /* ivar number 1 */
  1657. X    setivar(class,IVARS,cons(xlenter("%%CLASS"),getivar(class,IVARS)));
  1658. X    setivar(class,IVARCNT,cvfixnum((FIXTYPE)CLASSSIZE));
  1659. X    setivar(class,IVARTOTAL,cvfixnum((FIXTYPE)CLASSSIZE));
  1660. X    setivar(class,SUPERCLASS,object);
  1661. X    addmsg(class,"NEW","%CLASS-NEW");
  1662. X    addmsg(class,"ISNEW","%CLASS-ISNEW");
  1663. X    addmsg(class,"ANSWER","%CLASS-ANSWER");
  1664. X
  1665. X    /* patch the class into 'object' and 'class' */
  1666. X    setclass(object,class);
  1667. X    setclass(class,class);
  1668. X}
  1669. END_OF_FILE
  1670. if test 9292 -ne `wc -c <'Src/xsobj.c'`; then
  1671.     echo shar: \"'Src/xsobj.c'\" unpacked with wrong size!
  1672. fi
  1673. # end of 'Src/xsobj.c'
  1674. fi
  1675. if test -f 'Src/xsread.c' -a "${1}" != "-c" ; then 
  1676.   echo shar: Will not clobber existing file \"'Src/xsread.c'\"
  1677. else
  1678. echo shar: Extracting \"'Src/xsread.c'\" \(9004 characters\)
  1679. sed "s/^X//" >'Src/xsread.c' <<'END_OF_FILE'
  1680. X/* xsread.c - xscheme input routines */
  1681. X/*    Copyright (c) 1988, by David Michael Betz
  1682. X    All Rights Reserved
  1683. X    Permission is granted for unrestricted non-commercial use    */
  1684. X
  1685. X#include "xscheme.h"
  1686. X
  1687. X/* external variables */
  1688. Xextern LVAL true;
  1689. X
  1690. X/* external routines */
  1691. Xextern double atof();
  1692. Xextern ITYPE;
  1693. X
  1694. X/* forward declarations */
  1695. XLVAL read_list(),read_quote(),read_comma(),read_symbol();
  1696. XLVAL read_radix(),read_string(),read_special();
  1697. X
  1698. X/* xlread - read an expression */
  1699. Xint xlread(fptr,pval)
  1700. X  LVAL fptr,*pval;
  1701. X{
  1702. X    int ch;
  1703. X
  1704. X    /* check the next non-blank character */
  1705. X    while ((ch = scan(fptr)) != EOF)
  1706. X    switch (ch) {
  1707. X    case '(':
  1708. X        *pval = read_list(fptr);
  1709. X        return (TRUE);
  1710. X    case ')':
  1711. X        xlfail("misplaced right paren");
  1712. X    case '\'':
  1713. X        *pval = read_quote(fptr,"QUOTE");
  1714. X        return (TRUE);
  1715. X    case '`':
  1716. X        *pval = read_quote(fptr,"QUASIQUOTE");
  1717. X        return (TRUE);
  1718. X    case ',':
  1719. X        *pval = read_comma(fptr);
  1720. X        return (TRUE);
  1721. X    case '"':
  1722. X        *pval = read_string(fptr);
  1723. X        return (TRUE);
  1724. X    case '#':
  1725. X        *pval = read_special(fptr);
  1726. X        return (TRUE);
  1727. X    case ';':
  1728. X            read_comment(fptr);
  1729. X            break;
  1730. X    default:
  1731. X        xlungetc(fptr,ch);
  1732. X        *pval = read_symbol(fptr);
  1733. X        return (TRUE);
  1734. X    }
  1735. X    return (FALSE);
  1736. X}
  1737. X
  1738. X/* read_list - read a list */
  1739. XLOCAL LVAL read_list(fptr)
  1740. X  LVAL fptr;
  1741. X{
  1742. X    LVAL last,val;
  1743. X    int ch;
  1744. X    
  1745. X    cpush(NIL); last = NIL;
  1746. X    while ((ch = scan(fptr)) != EOF)
  1747. X    switch (ch) {
  1748. X    case ';':
  1749. X        read_comment(fptr);
  1750. X        break;
  1751. X    case ')':
  1752. X        return (pop());
  1753. X    default:
  1754. X        xlungetc(fptr,ch);
  1755. X        if (!xlread(fptr,&val))
  1756. X        xlfail("unexpected EOF");
  1757. X        if (val == xlenter(".")) {
  1758. X        if (last == NIL)
  1759. X            xlfail("misplaced dot");
  1760. X        read_cdr(fptr,last);
  1761. X        return (pop());
  1762. X        }
  1763. X        else {
  1764. X        val = cons(val,NIL);
  1765. X        if (last) rplacd(last,val);
  1766. X        else settop(val);
  1767. X        last = val;
  1768. X        }
  1769. X        break;
  1770. X    }
  1771. X    xlfail("unexpected EOF");
  1772. X}
  1773. X
  1774. X/* read_cdr - read the cdr of a dotted pair */
  1775. XLOCAL read_cdr(fptr,last)
  1776. X  LVAL fptr,last;
  1777. X{
  1778. X    LVAL val;
  1779. X    int ch;
  1780. X    
  1781. X    /* read the cdr expression */
  1782. X    if (!xlread(fptr,&val))
  1783. X    xlfail("unexpected EOF");
  1784. X    rplacd(last,val);
  1785. X    
  1786. X    /* check for the close paren */
  1787. X    while ((ch = scan(fptr)) == ';')
  1788. X    read_comment(fptr);
  1789. X    if (ch != ')')
  1790. X    xlfail("missing right paren");
  1791. X}
  1792. X
  1793. X/* read_comment - read a comment (to end of line) */
  1794. XLOCAL read_comment(fptr)
  1795. X  LVAL fptr;
  1796. X{
  1797. X    int ch;
  1798. X    while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
  1799. X    ;
  1800. X    if (ch != EOF) xlungetc(fptr,ch);
  1801. X}
  1802. X
  1803. X/* read_vector - read a vector */
  1804. XLOCAL LVAL read_vector(fptr)
  1805. X  LVAL fptr;
  1806. X{
  1807. X    int len=0,ch,i;
  1808. X    LVAL last,val;
  1809. X    
  1810. X    cpush(NIL); last = NIL;
  1811. X    while ((ch = scan(fptr)) != EOF)
  1812. X    switch (ch) {
  1813. X    case ';':
  1814. X        read_comment(fptr);
  1815. X        break;
  1816. X    case ')':
  1817. X        val = newvector(len);
  1818. X        for (last = pop(), i = 0; i < len; ++i, last = cdr(last))
  1819. X        setelement(val,i,car(last));
  1820. X        return (val);
  1821. X    default:
  1822. X        xlungetc(fptr,ch);
  1823. X        if (!xlread(fptr,&val))
  1824. X        xlfail("unexpected EOF");
  1825. X        val = cons(val,NIL);
  1826. X        if (last) rplacd(last,val);
  1827. X        else settop(val);
  1828. X        last = val;
  1829. X        ++len;
  1830. X        break;
  1831. X    }
  1832. X    xlfail("unexpected EOF");
  1833. X}
  1834. X
  1835. X/* read_comma - read a unquote or unquote-splicing expression */
  1836. XLOCAL LVAL read_comma(fptr)
  1837. X  LVAL fptr;
  1838. X{
  1839. X    int ch;
  1840. X    if ((ch = xlgetc(fptr)) == '@')
  1841. X    return (read_quote(fptr,"UNQUOTE-SPLICING"));
  1842. X    else {
  1843. X    xlungetc(fptr,ch);
  1844. X    return (read_quote(fptr,"UNQUOTE"));
  1845. X    }
  1846. X}
  1847. X
  1848. X/* read_quote - parse the tail of a quoted expression */
  1849. XLOCAL LVAL read_quote(fptr,sym)
  1850. X  LVAL fptr; char *sym;
  1851. X{
  1852. X    LVAL val;
  1853. X    if (!xlread(fptr,&val))
  1854. X    xlfail("unexpected EOF");
  1855. X    cpush(cons(val,NIL));
  1856. X    settop(cons(xlenter(sym),top()));
  1857. X    return (pop());
  1858. X}
  1859. X
  1860. X/* read_symbol - parse a symbol name (or a number) */
  1861. XLOCAL LVAL read_symbol(fptr)
  1862. X  LVAL fptr;
  1863. X{
  1864. X    char buf[STRMAX+1];
  1865. X    LVAL val;
  1866. X    if (!getsymbol(fptr,buf))
  1867. X    xlfail("expecting symbol name");
  1868. X    return (isnumber(buf,&val) ? val : xlenter(buf));
  1869. X}
  1870. X
  1871. X/* read_string - parse a string */
  1872. XLOCAL LVAL read_string(fptr)
  1873. X  LVAL fptr;
  1874. X{
  1875. X    char buf[STRMAX+1];
  1876. X    int ch,i;
  1877. X
  1878. X    /* get symbol name */
  1879. X    for (i = 0; (ch = checkeof(fptr)) != '"'; ) {
  1880. X    if (ch == '\\')
  1881. X        ch = checkeof(fptr);
  1882. X    if (i < STRMAX)
  1883. X        buf[i++] = ch;
  1884. X    }
  1885. X    buf[i] = '\0';
  1886. X
  1887. X    /* return a string */
  1888. X    return (cvstring(buf));
  1889. X}
  1890. X
  1891. X/* read_special - parse an atom starting with '#' */
  1892. XLOCAL LVAL read_special(fptr)
  1893. X  LVAL fptr;
  1894. X{
  1895. X    char buf[STRMAX+1],buf2[STRMAX+3];
  1896. X    int ch;
  1897. X    switch (ch = checkeof(fptr)) {
  1898. X    case '!':
  1899. X    if (getsymbol(fptr,buf)) {
  1900. X        if (strcmp(buf,"TRUE") == 0)
  1901. X        return (true);
  1902. X        else if (strcmp(buf,"FALSE") == 0)
  1903. X        return (NIL);
  1904. X        else if (strcmp(buf,"NULL") == 0)
  1905. X        return (NIL);
  1906. X        else {
  1907. X        sprintf(buf2,"#!%s",buf);
  1908. X        return (xlenter(buf2));
  1909. X        }
  1910. X    }
  1911. X    else
  1912. X        xlfail("expecting symbol after '#!'");
  1913. X    break;
  1914. X    case '\\':
  1915. X    ch = checkeof(fptr);    /* get the next character */
  1916. X    xlungetc(fptr,ch);    /* but allow getsymbol to get it also */
  1917. X    if (getsymbol(fptr,buf)) {
  1918. X        if (strcmp(buf,"NEWLINE") == 0)
  1919. X        ch = '\n';
  1920. X        else if (strcmp(buf,"SPACE") == 0)
  1921. X        ch = ' ';
  1922. X        else if (strlen(buf) > 1)
  1923. X        xlerror("unexpected symbol after '#\\'",cvstring(buf));
  1924. X    }
  1925. X    else            /* wasn't a symbol, get the character */
  1926. X        ch = checkeof(fptr);
  1927. X    return (cvchar(ch));
  1928. X    case '(':
  1929. X    return (read_vector(fptr));
  1930. X    case 'b':
  1931. X    case 'B':
  1932. X    return (read_radix(fptr,2));
  1933. X    case 'o':
  1934. X    case 'O':
  1935. X    return (read_radix(fptr,8));
  1936. X    case 'd':
  1937. X    case 'D':
  1938. X    return (read_radix(fptr,10));
  1939. X    case 'x':
  1940. X    case 'X':
  1941. X        return (read_radix(fptr,16));
  1942. X    default:
  1943. X    xlungetc(fptr,ch);
  1944. X    if (getsymbol(fptr,buf)) {
  1945. X        if (strcmp(buf,"T") == 0)
  1946. X        return (true);
  1947. X        else if (strcmp(buf,"F") == 0)
  1948. X        return (NIL);
  1949. X        else
  1950. X        xlerror("unexpected symbol after '#'",cvstring(buf));
  1951. X    }
  1952. X    else
  1953. X        xlerror("unexpected character after '#'",cvchar(xlgetc(fptr)));
  1954. X    break;
  1955. X    }
  1956. X}
  1957. X
  1958. X/* read_radix - read a number in a specified radix */
  1959. XLOCAL LVAL read_radix(fptr,radix)
  1960. X  LVAL fptr; int radix;
  1961. X{
  1962. X    FIXTYPE val;
  1963. X    int ch;
  1964. X
  1965. X    /* get symbol name */
  1966. X    for (val = (FIXTYPE)0; (ch = xlgetc(fptr)) != EOF && issym(ch); ) {
  1967. X        if (islower(ch)) ch = toupper(ch);
  1968. X    if (!isradixdigit(ch,radix))
  1969. X        xlerror("invalid digit",cvchar(ch));
  1970. X        val = val * radix + getdigit(ch);
  1971. X    }
  1972. X
  1973. X    /* save the break character */
  1974. X    xlungetc(fptr,ch);
  1975. X
  1976. X    /* return the number */
  1977. X    return (cvfixnum(val));
  1978. X}
  1979. X
  1980. X/* isradixdigit - check to see if a character is a digit in a radix */
  1981. XLOCAL int isradixdigit(ch,radix)
  1982. X  int ch,radix;
  1983. X{
  1984. X    switch (radix) {
  1985. X    case 2:    return (ch >= '0' && ch <= '1');
  1986. X    case 8:    return (ch >= '0' && ch <= '7');
  1987. X    case 10:    return (ch >= '0' && ch <= '9');
  1988. X    case 16:    return ((ch >= '0' && ch <= '9')
  1989. X                     || (ch >= 'A' && ch <= 'F'));
  1990. X    }
  1991. X}
  1992. X
  1993. X/* getdigit - convert an ascii code to a digit */
  1994. XLOCAL int getdigit(ch)
  1995. X  int ch;
  1996. X{
  1997. X    return (ch <= '9' ? ch - '0' : ch - 'A' + 10);
  1998. X}
  1999. X
  2000. X/* getsymbol - get a symbol name */
  2001. XLOCAL int getsymbol(fptr,buf)
  2002. X  LVAL fptr; char *buf;
  2003. X{
  2004. X    int ch,i;
  2005. X
  2006. X    /* get symbol name */
  2007. X    for (i = 0; (ch = xlgetc(fptr)) != EOF && issym(ch); )
  2008. X    if (i < STRMAX)
  2009. X        buf[i++] = (islower(ch) ? toupper(ch) : ch);
  2010. X    buf[i] = '\0';
  2011. X
  2012. X    /* save the break character */
  2013. X    xlungetc(fptr,ch);
  2014. X    return (buf[0] != '\0');
  2015. X}
  2016. X
  2017. X/* isnumber - check if this string is a number */
  2018. XLOCAL int isnumber(str,pval)
  2019. X  char *str; LVAL *pval;
  2020. X{
  2021. X    int dl,dot,dr;
  2022. X    char *p;
  2023. X
  2024. X    /* initialize */
  2025. X    p = str; dl = dot = dr = 0;
  2026. X
  2027. X    /* check for a sign */
  2028. X    if (*p == '+' || *p == '-')
  2029. X    p++;
  2030. X
  2031. X    /* check for a string of digits */
  2032. X    while (isdigit(*p))
  2033. X    p++, dl++;
  2034. X
  2035. X    /* check for a decimal point */
  2036. X    if (*p == '.') {
  2037. X    p++; dot = 1;
  2038. X    while (isdigit(*p))
  2039. X        p++, dr++;
  2040. X    }
  2041. X
  2042. X    /* check for an exponent */
  2043. X    if ((dl || dr) && *p == 'E') {
  2044. X    p++; dot = 1;
  2045. X
  2046. X    /* check for a sign */
  2047. X    if (*p == '+' || *p == '-')
  2048. X        p++;
  2049. X
  2050. X    /* check for a string of digits */
  2051. X    while (isdigit(*p))
  2052. X        p++, dr++;
  2053. X    }
  2054. X
  2055. X    /* make sure there was at least one digit and this is the end */
  2056. X    if ((dl == 0 && dr == 0) || *p)
  2057. X    return (FALSE);
  2058. X
  2059. X    /* convert the string to an integer and return successfully */
  2060. X    if (pval) {
  2061. X    if (*str == '+') ++str;
  2062. X    if (str[strlen(str)-1] == '.') str[strlen(str)-1] = 0;
  2063. X    *pval = (dot ? cvflonum(atof(str)) : cvfixnum(ICNV(str)));
  2064. X    }
  2065. X    return (TRUE);
  2066. X}
  2067. X
  2068. X/* scan - scan for the first non-blank character */
  2069. XLOCAL int scan(fptr)
  2070. X  LVAL fptr;
  2071. X{
  2072. X    int ch;
  2073. X
  2074. X    /* look for a non-blank character */
  2075. X    while ((ch = xlgetc(fptr)) != EOF && isspace(ch))
  2076. X    ;
  2077. X
  2078. X    /* return the character */
  2079. X    return (ch);
  2080. X}
  2081. X
  2082. X/* checkeof - get a character and check for end of file */
  2083. XLOCAL int checkeof(fptr)
  2084. X  LVAL fptr;
  2085. X{
  2086. X    int ch;
  2087. X    if ((ch = xlgetc(fptr)) == EOF)
  2088. X    xlfail("unexpected EOF");
  2089. X    return (ch);
  2090. X}
  2091. X
  2092. X/* issym - is this a symbol character? */
  2093. XLOCAL int issym(ch)
  2094. X  int ch;
  2095. X{
  2096. X    register char *p;
  2097. X    if (!isspace(ch)) {
  2098. X    for (p = "()';"; *p != '\0'; )
  2099. X        if (*p++ == ch)
  2100. X        return (FALSE);
  2101. X    return (TRUE);
  2102. X    }
  2103. X    return (FALSE);
  2104. X}
  2105. END_OF_FILE
  2106. if test 9004 -ne `wc -c <'Src/xsread.c'`; then
  2107.     echo shar: \"'Src/xsread.c'\" unpacked with wrong size!
  2108. fi
  2109. # end of 'Src/xsread.c'
  2110. fi
  2111. echo shar: End of archive 2 \(of 7\).
  2112. cp /dev/null ark2isdone
  2113. MISSING=""
  2114. for I in 1 2 3 4 5 6 7 ; do
  2115.     if test ! -f ark${I}isdone ; then
  2116.     MISSING="${MISSING} ${I}"
  2117.     fi
  2118. done
  2119. if test "${MISSING}" = "" ; then
  2120.     echo You have unpacked all 7 archives.
  2121.     rm -f ark[1-9]isdone
  2122. else
  2123.     echo You still need to unpack the following archives:
  2124.     echo "        " ${MISSING}
  2125. fi
  2126. ##  End of shell archive.
  2127. exit 0
  2128. -- 
  2129. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  2130. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  2131. Post requests for sources, and general discussion to comp.sys.amiga.
  2132.